package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/samber/do/v2"

	"gitee.com/monkeyPP/happy-mall/services/userservice/internal/application"
	"gitee.com/monkeyPP/happy-mall/services/userservice/internal/domain/entity"
	"gitee.com/monkeyPP/happy-mall/services/userservice/internal/interfaces/api/request"
	"gitee.com/monkeyPP/happy-mall/services/userservice/internal/interfaces/api/response"
)

type UserHandler interface {
	Register(c *gin.Context)
	Login(c *gin.Context)
	Profile(c *gin.Context)
	Logout(c *gin.Context)
}

type UserHandlerImpl struct {
	userApp application.UserApp
}

func NewUserHandler(i do.Injector) (UserHandler, error) {
	userApp := do.MustInvoke[application.UserApp](i)
	return &UserHandlerImpl{
		userApp: userApp,
	}, nil
}

func (h *UserHandlerImpl) Register(c *gin.Context) {
	var req request.UserRegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Password != req.ConfirmPassword {
		c.JSON(http.StatusBadRequest, gin.H{"error": "password and confirm password error"})
		return
	}

	if user, err := h.userApp.Register(c, &entity.User{
		Name:     req.Username,
		Password: req.Password,
	}); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
	} else {
		c.JSON(http.StatusOK, gin.H{
			"code": http.StatusOK,
			"user": response.UserRegisterResponse{
				Name: user.Name,
			},
		})
	}
}

func (h *UserHandlerImpl) Login(c *gin.Context) {
	var req request.UserLoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	tokenPair, err := h.userApp.Login(c, &entity.User{
		Name:     req.Username,
		Password: req.Password,
	})
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"token": response.UserLoginResponse{
			AccessToken:  tokenPair.AccessToken,
			RefreshToken: tokenPair.RefreshToken,
		},
	})
}

func (h *UserHandlerImpl) Profile(c *gin.Context) {
	value, exists := c.Get("userID")

	// TODO 后面去查询 db 的逻辑可以后面再写

	if !exists {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "user id not found"})
	} else {
		c.JSON(http.StatusOK, gin.H{
			"code":   http.StatusOK,
			"userID": value,
		})
	}
}

func (h *UserHandlerImpl) Logout(c *gin.Context) {
	userID, _ := c.Get("userID")

	err := h.userApp.Logout(c, userID.(string))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":  http.StatusInternalServerError,
			"error": err.Error(),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
	})
}
